package com.yss.sofa.ide.builder.dbscript.ui.wizard;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.slf4j.LoggerFactory;

import com.yss.sofa.common.jdbc.DBType;
import com.yss.sofa.common.util.PathUtil;
import com.yss.sofa.common.util.io.FileUtil;
import com.yss.sofa.common.util.io.ListFileFilter;
import com.yss.sofa.ide.builder.dbscript.model.DBInfo;
import com.yss.sofa.ide.builder.dbscript.model.ScriptInfo;
import com.yss.sofa.ide.builder.dbscript.service.DBSchemaService;
import com.yss.sofa.ide.builder.dbscript.service.DBTypeMapService;
import com.yss.sofa.ide.builder.dbscript.service.GenerateScriptFileService;
import com.yss.sofa.ide.builder.dbscript.ui.internal.Config;
import com.yss.sofa.ide.builder.dbscript.util.XMLUtil;
import com.yss.sofa.ide.builder.dbscript.vo.DBScript;
import com.yss.sofa.ide.builder.packer.AppContext;
import com.yss.sofa.ide.builder.packer.PathConst;
import com.yss.sofa.ide.builder.packer.ProjectConst;
import com.yss.sofa.ide.builder.packer.service.ProjectConfigService;
import com.yss.sofa.ide.builder.packer.ui.project.ProjectUtil;
import com.yss.sofa.ide.builder.packer.vo.ProjectConfig;
import com.yss.sofa.ide.ui.wizard.BaseWizard;
import com.yss.sofa.ide.util.Logger;

public class CreateDBManagerWizard extends BaseWizard implements INewWizard {

  protected org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());

  private boolean isFirst = true;
  private ScriptInfo info;
  private NewDBManagerProjectWizardPage projectPage;
  private ImportSourceTypePage sourcePage;
  private GlobalTypeMappingPage mappingPage;
  private ProjectConfig projectConfig;
  private ListFileFilter listFileFilter;
  private IProject project = ProjectUtil.getSelectionProject(null);

  public IProject getProject() {
    return project;
  }

  public void setProject(IProject project) {
    this.project = project;
  }

  public CreateDBManagerWizard() {
    setWindowTitle(Messages.CreateDBManagerWizard_TITLE);
    setNeedsProgressMonitor(true);
    setDialogSettings(new DialogSettings(CreateDBManagerWizard.class.getName()));
    this.info = new ScriptInfo();
    this.info.setSource(new DBInfo());
    this.info.setTarget(new DBInfo());
  }

  public CreateDBManagerWizard(ScriptInfo info) {
    this.info = info;
    setWindowTitle(Messages.CreateDBManagerWizard_TITLE);
    setNeedsProgressMonitor(true);
    setDialogSettings(new DialogSettings(CreateDBManagerWizard.class.getName()));
    this.isFirst = false;
  }

  @Override
  public void init(IWorkbench workbench, IStructuredSelection selection) {
  }

  @Override
  public void addPages() {
    listFileFilter = new ListFileFilter("^*.svn", true, true);

    this.projectPage = new NewDBManagerProjectWizardPage(this.info, this.isFirst);
    this.sourcePage = new ImportSourceTypePage(this.info);
    this.mappingPage = new GlobalTypeMappingPage(this.info);
    addPage(this.projectPage);
    addPage(this.sourcePage);
    addPage(this.mappingPage);
  }

  @Override
  public boolean canFinish() {
    return super.canFinish() && this.sourcePage.getControl() != null;
  }

  @Override
  public boolean performFinish() {
    projectPage.getPageData();

    File file = project.getFile(ProjectConst.PACKER_FILE_NAME).getLocation().toFile();

    ProjectConfigService service = AppContext.getService(ProjectConfigService.ID, ProjectConfigService.class);
    projectConfig = service.load(file);
    if (this.isFirst) {
      createProjectAndSqlFile(project);
    } else {
      updateProjectAndSqlFile(project);
    }
    try {
      // copy to container
      copyToContainer(projectConfig);
      project.refreshLocal(IProject.DEPTH_INFINITE, null);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return true;
  }

  private void copyToContainer(ProjectConfig projectConfig) throws IOException {
    String resourcePath = projectConfig.getResourcePath();
    String src = PathUtil.getFilePath(resourcePath, projectConfig.getDbScriptDirectory(), "sql/init");
    String out = PathUtil.getFilePath(resourcePath, projectConfig.getContainerDirectory(),
            "WebContent/WEB-INF/sofa-container/install/database");
    FileUtil.copyFiles(src, out, true, listFileFilter);
    logger.info("复制文件到：" + out);
  }

  private void createProjectAndSqlFile(final IProject project) {
    try {
      // createProject(project, location);
      createUserMapFile(project, new DBTypeMapService());
      createSql(this.info, project, this.projectPage);
      createDBScriptFile(info, project);
      // project.getFile(".UserDBTypeMap.xml").getFullPath().toFile();
    } catch (Exception e) {
      e.printStackTrace();
      Logger.error(e);
    }
  }

  private void createUserMapFile(IProject project, DBTypeMapService dbTypeMapService) throws IOException {
    File file = project.getFile(Config.USER_DBTYPE_MAP_PATH).getLocation().toFile();
    if (!file.exists()) {
      file.getParentFile().mkdirs();
      file.createNewFile();
    }
    dbTypeMapService.saveDBTypeMap(this.mappingPage.getMap(), file.getAbsolutePath());
  }

  // private void createProject(final IProject project, final IPath location) throws CoreException, Exception {
  // // createProjectWithNatures(project, location, new String[] { Messages.CreateDBManagerWizard_DBSCRIPT_NATURE });
  // createDataFolder(project);
  // createDBScriptFile(project);
  // }

  // private void createProjectWithNatures(IProject project, IPath location, String[] strings) throws CoreException {
  // if (project == null) {
  // // throw new IllegalArgumentException(Messages.CreateDBManagerWizard_PROJECT_IS_NOT_NULL);
  // }
  // createBaseProject(project, location);
  // if (!project.isOpen()) {
  // project.open(new NullProgressMonitor());
  // }
  // addNature(project, strings, new NullProgressMonitor());
  // }

  // private void addNature(IProject project, String[] strings, NullProgressMonitor monitor) throws CoreException {
  // if (project == null) {
  // throw new IllegalArgumentException(Messages.CreateDBManagerWizard_NATURE_ERROR);
  // }
  // if (ArrayUtils.isEmpty(strings)) {
  // return;
  // }
  // IProjectDescription description = project.getDescription();
  // String[] prevNatures = description.getNatureIds();
  // Set<String> newNatures = new HashSet<String>();
  // newNatures.addAll(Arrays.asList(prevNatures));
  // for (String nature : strings) {
  // newNatures.add(nature);
  // }
  // description.setNatureIds(newNatures.toArray(new String[newNatures.size()]));
  // project.setDescription(description, monitor);
  // }

  // private void createBaseProject(IProject project, IPath location) throws CoreException {
  // if (!Platform.getLocation().equals(location)) {
  // IProjectDescription desc = project.getWorkspace().newProjectDescription(project.getName());
  // desc.setLocation(location);
  // project.create(desc, new NullProgressMonitor());
  // } else {
  // project.create(new NullProgressMonitor());
  // }
  //
  // }

  private void createDBScriptFile(ScriptInfo info, final IProject project) throws Exception, CoreException {
    IFile file = project.getFolder(Config.DATA).getFile(info.getProjectName() + Config.SCRIPTE);
    File parentFile = file.getLocation().toFile().getParentFile();
    parentFile.mkdirs();
    project.refreshLocal(IProject.DEPTH_INFINITE, null);

    if (file.exists()) {
      file.setContents(getInputStream(), true, false, new NullProgressMonitor());
    } else {
      file.create(getInputStream(), true, new NullProgressMonitor());
    }
  }

  private ByteArrayInputStream getInputStream() throws Exception {
    String content = XMLUtil.createMXL(this.info);
    ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes("UTF-8"));
    return bis;
  }

  private void createDataFolder(final IProject project) throws CoreException {
    IFolder iFolder = project.getFolder(Config.DATA);
    if (!iFolder.exists()) {
      iFolder.create(false, true, new NullProgressMonitor());
    }
  }

  private void createSql(ScriptInfo scInfo, IProject project, NewDBManagerProjectWizardPage projectPage) {
    try {
      GenerateScriptFileService generateScriptFileService = new GenerateScriptFileService();
      for (String targetType : scInfo.getTargetTypes()) {
        DBSchemaService dbSchemaToDBScriptService = new DBSchemaService(DBType.getEnumType(scInfo.getSourceType()),
                DBType.getEnumType(targetType), this.mappingPage.getMap());
        List<DBScript> dbScripts = dbSchemaToDBScriptService.parseToDBScript(scInfo.getCreateTableFiles(),
                scInfo.getInsertDataFiles());
        String createFilePath = getFilePath(project, targetType, scInfo.getCreateFileName());
        String insertFilePath = getFilePath(project, targetType, scInfo.getInsertFileName());
        String dropFilePath = getFilePath(project, targetType, scInfo.getDropFileName());
        generateScriptFileService.generateDropFile(dbScripts, createFilePath, insertFilePath, dropFilePath);
      }
      project.refreshLocal(IProject.DEPTH_INFINITE, null);
      // MessageDialog.openInformation(null, "finish", "create DBinfo is success");
    } catch (IOException e) {
      e.printStackTrace();
      Logger.error("SQL File create Failure!", e);
    } catch (CoreException e) {
      e.printStackTrace();
      Logger.error("Folder create Failure!", e);
    }
  }

  private String getFilePath(IProject project, String type, String fileName) throws CoreException {
    String filePath = PathUtil.getFilePath(projectConfig.getResourcePath(), projectConfig.getDbScriptDirectory());
    String sqlDir = PathConst.SOURCE_SQL_ROOT_PATH;
    filePath = PathUtil.getFilePath(filePath, sqlDir);
    File file = new File(filePath, type + File.separator + fileName);
    return file.getAbsolutePath();
  }

  // private String getDefaultFilePath(IProject project, String targetType, String fileName) throws CoreException {
  // if (this.projectPage.isDefaultDataPath()) {
  // IFolder iFolder = project.getFolder(Config.DATA).getFolder(targetType);
  // if (!iFolder.exists()) {
  // iFolder.create(false, true, new NullProgressMonitor());
  // }
  // }
  // return project.getLocation().toString() + File.separator + Config.DATA + File.separator + targetType
  // + File.separator + project.getName() + fileName;
  // }

  // private String getSpecifFilePath(IProject project, NewDBManagerProjectWizardPage projectPage, String targetType,
  // String fileName) {
  // return projectPage.getCreateDataPath() + File.separator + targetType + File.separator + project.getName()
  // + fileName;
  // }

  private void updateProjectAndSqlFile(IProject project) {
    try {
      createDataFolder(project);
      createDBScriptFile(info, project);
      createUserMapFile(project, new DBTypeMapService());
      createSql(this.info, project, this.projectPage);
    } catch (IOException e) {
      e.printStackTrace();
      Logger.error(e);
    } catch (CoreException e) {
      e.printStackTrace();
      Logger.error(e);
    } catch (Exception e) {
      e.printStackTrace();
      Logger.error(e);
    }
  }
}
